package com.cf.user.permission.service;

import com.cf.constant.EnumReturnCode;
import com.cf.crud.service.AbsBaseService;
import com.cf.exception.BizException;
import com.cf.id.SnowflakeId;
import com.cf.mapper.BeanMapper;
import com.cf.user.permission.dao.RoleWithPermissionDao;
import com.cf.user.permission.dao.SystemPermissionDao;
import com.cf.user.permission.dao.SystemRoleDao;
import com.cf.user.permission.dao.UserWithRoleDao;
import com.cf.user.permission.model.RoleWithPermission;
import com.cf.user.permission.model.SystemPermission;
import com.cf.user.permission.model.SystemRole;
import com.cf.user.permission.model.UserWithRole;
import com.cf.user.permission.vo.Menu;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.OrderComparator;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * game-server-DefaultPermissionService
 *
 * @author <a href="2428922347@qq.com">Zhu mingming</a>
 * @info
 * @since 2018/5/29 下午 05:21
 */
public class SystemPermissionServiceImpl extends AbsBaseService<SystemPermission, SystemPermissionDao> implements SystemPermissionService {

    @Autowired
    private SnowflakeId id;

    @Autowired
    private UserWithRoleDao userWithRoleDao;

    @Autowired
    private RoleWithPermissionDao roleWithPermissionDao;

    @Autowired
    private SystemPermissionDao systemPermissionDao;

    @Autowired
    private SystemRoleDao systemRoleDao;

    @Autowired
    private BeanMapper beanMapper;

    @Override
    public List<SystemRole> getRole() {
        return systemRoleDao.selectAll();
    }

    @Override
    public void addRole(SystemRole systemRole) {
        Assert.notNull(systemRole, "保存角色时，角色信息不能为空");
        Assert.notNull(systemRole.getRoleCode(), "角色Code不能为空");
        Assert.notNull(systemRole.getRoleName(), "角色Name不能为空");
        systemRole.setId(id.nextId());
        systemRoleDao.insert(systemRole);
    }

    @Override
    public void delRole(long id) {
        systemRoleDao.deleteByPrimaryKey(id);
    }

    @Override
    public void updateRole(SystemRole systemRole) {
        if (systemRole.getId() == 0) {
            throw new BizException(EnumReturnCode.ERROR.getCode(), "更新数据Id缺失，不能为0");
        }
        systemRoleDao.updateByPrimaryKey(systemRole);
    }

    @Override
    public List<SystemPermission> getRolePermission(long roleId) {
        return roleWithPermissionDao.getPermissionByRoleId(roleId);
    }

    @Override
    public void addRolePermission(long roleId, long permissionId) {
        RoleWithPermission roleWithPermission = new RoleWithPermission();
        roleWithPermission.setId(id.nextId());
        roleWithPermission.setPermissionId(permissionId);
        roleWithPermission.setRoleId(roleId);
        roleWithPermissionDao.insert(roleWithPermission);
    }

    @Override
    public void delRolePermission(long id) {
        roleWithPermissionDao.deleteByPrimaryKey(id);
    }

    @Override
    public List<SystemPermission> getPermission() {
        return systemPermissionDao.selectAll();
    }

    @Override
    public void addPermission(SystemPermission systemPermission) {
        Assert.notNull(systemPermission, "保存权限时，权限不能为空");
        Assert.notNull(systemPermission.getPermissionCode(), "permissionCode不能为空");
        Assert.notNull(systemPermission.getPermissionName(), "permissionName不能为空");
        systemPermission.setId(id.nextId());
        systemPermissionDao.insert(systemPermission);
    }

    @Override
    public void delPermission(long id) {
        systemPermissionDao.deleteByPrimaryKey(id);
    }

    @Override
    public boolean hasPermission(long userId, String path) {
        SystemPermission systemPermission = systemPermissionDao.selectByPermissionUrl(path);
        List<SystemPermission> userPermission = getUserPermission(userId);
        if (userPermission.contains(systemPermission))
            return true;
        return false;
    }

    private List<SystemPermission> getUserPermission(long userId) {
        Set<SystemPermission> permissionSet = new HashSet();
        List<UserWithRole> userWithRoles = userWithRoleDao.selectByUserId(userId);
        userWithRoles.forEach(userWithRole -> {
            permissionSet.addAll(roleWithPermissionDao.getPermissionByRoleId(userWithRole.getRoleId()));
        });
        ArrayList list = new ArrayList();
        list.addAll(permissionSet);
        return list;
    }

    @Override
    public List<Menu> getUserMenu(long userId) {
        List<SystemPermission> userPermission = getUserPermission(userId);
        return toMenu(userPermission);
    }

    private List<Menu> toMenu(List<SystemPermission> userPermission) {
        List<Menu> menus = new ArrayList<>();
        userPermission.forEach(systemPermission -> {
            if (systemPermission.getParentId() == 0) {
                menus.add(beanMapper.map(systemPermission, Menu.class));
            }
        });
        menus.forEach(m -> {
            userPermission.forEach(systemPermission -> {
                if (systemPermission.getParentId() == m.getId())
                    m.addChild(systemPermission);
            });
            OrderComparator.sort(m.getChild());
        });
        return menus;
    }

    @Override
    public Class getTargetClass() {
        return SystemPermission.class;
    }

    public List<Menu> getPermissionTree() {
        Set<SystemPermission> permissionSet = new HashSet();
        List<SystemPermission> permission = getPermission();
        permissionSet.addAll(permission);
        ArrayList<SystemPermission> list = new ArrayList();
        list.addAll(permissionSet);
        return toMenu(list);
    }

    /**
     * 更新角色的权限
     *
     * @param roleId
     * @param permissionId
     * @return
     */
    public boolean updateRolePermission(long roleId, List<Long> permissionId) {
        roleWithPermissionDao.deleteByRoleId(roleId);
        permissionId.forEach(pId -> {
            this.addRolePermission(roleId, pId);
        });
        return true;
    }

    @Override
    public List<SystemPermission> userPermission(long userId) {
        return getUserPermission(userId);
    }
}
